using System;
using UnityEngine;
using UnityEngine.Playables;

namespace Taco.Timeline
{
    [ScriptGuid("31085f11443fe1347b871c5d69db3774"), IconGuid("e28acf5dc5b2e3d4a97920bf4e831c87"), Ordered(3), Color(201, 060, 032)]
    public class TreeTrack : Track<TreeClipPlayable>
    {
        public override void Bind()
        {
            TrackPlayable = Playable.Create(Timeline.PlayableGraph, Clips.Count);
            base.Bind();
        }

#if UNITY_EDITOR

        public override Type ClipType => typeof(TreeClip);

        public override Clip AddClip(UnityEngine.Object referenceObject, int frame)
        {
            TreeClip clip = new TreeClip(referenceObject as TimelineRunningTree, this, frame);
            m_Clips.Add(clip);
            return clip;
        }
        public override bool DragValid()
        {
            return UnityEditor.DragAndDrop.objectReferences.Length == 1 && UnityEditor.DragAndDrop.objectReferences[0] is TimelineRunningTree;
        }
#endif
    }

    [ScriptGuid("31085f11443fe1347b871c5d69db3774"), Color(201, 060, 032)]
    public partial class TreeClip : Clip
    {
        [ShowInInspector, OnValueChanged("OnClipChanged", "RebindTimeline"), HorizontalGroup("TreePrefab")]
        public TimelineRunningTree Tree;
        [ShowInInspector, ReadOnly, HorizontalGroup("TreeInstance"), ShowIf("ShowIf")]
        public TimelineRunningTree TreeInstance;




        public TreeClipPlayable ParticleClipPlayable => ClipPlayable as TreeClipPlayable;
        public TreeClip(Track track, int frame) : base(track, frame)
        {
        }
        public TreeClip(TimelineRunningTree tree, Track track, int frame) : base(track, frame)
        {
            Tree = tree;
        }

#if UNITY_EDITOR

        public override string Name => Tree ? Tree.name : base.Name;
        public override ClipCapabilities Capabilities => ClipCapabilities.Resizable;

        void OnClipChanged()
        {
            OnNameChanged?.Invoke();
        }

        [Button("Open"), HorizontalGroup("TreePrefab")]
        void OpenTreePrefab()
        {
            if (Tree)
            {
                TreeDesigner.Editor.TreeWindowUtility.OpenTree(Tree);
            }
        }
        [Button("Open"), HorizontalGroup("TreeInstance"), ShowIf("ShowIf")]
        void OpenTreeInstance()
        {
            if (TreeInstance)
            {
                TreeDesigner.Editor.TreeWindowUtility.OpenTree(TreeInstance);
            }
        }
        bool ShowIf()
        {
            return Application.isPlaying;
        }
#endif
    }

    public class TreeClipPlayable : TimelineClipPlayable
    {
        public TreeClip TreeClip { get; private set; }
        public TimelineRunningTree TreeInstance { get; private set; }

        public TreeClipPlayable() { }

        public override void Initialize(Clip clip, Playable owner, Timeline timeline)
        {
            base.Initialize(clip, owner, timeline);

            TreeClip = clip as TreeClip;
            Instantiate();
        }
        public override void OnEnable()
        {
            base.OnEnable();
            TreeInstance?.OnTreeEnable();
        }
        public override void OnDisable()
        {
            base.OnDisable();
            TreeInstance?.OnTreeDisable();
        }
        public override void OnDestroy()
        {
            base.OnDestroy();
            if (Application.isPlaying)
            {
                if (TreeInstance)
                {
                    TreeInstance.OnTreeDestroy();
                    TreeInstance.DisposeTree();
                    UnityEngine.Object.DestroyImmediate(TreeInstance);
                    TreeInstance = null;
                    TreeClip.TreeInstance = null;
                }
            }
            else
            {
                if (TreeInstance.IsValid)
                {
                    TreeInstance.OnTreeDestroy();
                    TreeInstance.DisposeTree();
                    TreeInstance = null;
                }
            }
        }
        public override void PrepareFrame(Playable playable, FrameData info)
        {
            base.PrepareFrame(playable, info);
            if (TreeInstance && TreeInstance.Enable)
            {
                //Tree Window Close Will Dispose Tree
                if(!TreeInstance.IsValid)
                    TreeInstance.InitTree();

                TreeInstance.UpdateTree(info.deltaTime);
            }
        }

        void Instantiate()
        {
            if (TreeClip.Tree)
            {
                if (Application.isPlaying)
                {
                    TreeInstance = UnityEngine.Object.Instantiate(TreeClip.Tree);
                    TreeInstance.InitTree(this);
                    TreeClip.TreeInstance = TreeInstance;
                }
                else
                {
                    TreeInstance = TreeClip.Tree;
                    TreeInstance.InitTree(this);
                }
            }
        }
    }
}